var digits = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];
var tens = ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
function numberToEnglish(n) {
    console.log(n);
    if (Number.isNaN(n)) throw 'error:NaN';
    n = +n;
    var sign = n < 0 ? 'negative' : '';
    s = '' + Math.abs(n);
    var i = +s.split('.')[0];
    var s_f = s.split('.')[1] || '';
    var int_part = i_to_e(i);
    var fraction_part = [...s_f].map(v => digits[+v]).join(' ');
    var positive = int_part + (s_f ? ` point ${fraction_part}` : '');
    return sign ? sign + ' ' + positive : positive;
}

function i_to_e(i) {
    if (i === Infinity) return 'infinity';
    else if (i < 20) return digits[i];
    else if (i < 100) return tens[Math.floor(i / 10) - 2] + (i % 10 ? '-' + i_to_e(i % 10) : '');
    else if (i < 1000) return i_to_e(Math.floor(i / 100)) + ' hundred' + (i % 100 ? ' and ' + i_to_e(i % 100) : '');
    else if (i < 10 ** 6) return i_to_e(Math.floor(i / 1000)) + ' thousand' + (i % 1000 ? (i % 1000 < 100 ? ' and ' : ' ') + i_to_e(i % 1000) : '');
    else if (i < 10 ** 9) return i_to_e(Math.floor(i / 10 ** 6)) + ' million' + (i % 10 ** 6 ? (i % 10 ** 6 < 100 ? ' and ' : ' ') + i_to_e(i % 10 ** 6) : '');
    else if (i < 10 ** 12) return i_to_e(Math.floor(i / 10 ** 9)) + ' billion' + (i % 10 ** 9 ? (i % 10 ** 9 < 100 ? ' and ' : ' ') + i_to_e(i % 10 ** 9) : '');
    else if (i < 10 ** 15) return i_to_e(Math.floor(i / 10 ** 12)) + ' trillion' + (i % 10 ** 12 ? (i % 10 ** 12 < 100 ? ' and ' : ' ') + i_to_e(i % 10 ** 12) : '');
    else return i_to_e(Math.floor(i / 10 ** 15)) + ' quadrillion' + (i % 10 ** 15 ? (i % 10 ** 15 < 100 ? ' and ' : ' ') + i_to_e(i % 10 ** 15) : '');
}